/******************************************************************************
*
* Copyright (C), 2013, mophie. Co., Ltd. All Rights Reserved. 
*
* Version: v1.0.0
* $$Datae: 2013-7-5  
*
* Description:    
*   IIC Function
*
* Function List: 
* 
* History:        
*         1. $$data:  2013-7-5
*            Author:  JPM team         
*
******************************************************************************/
/***Include file list*********************************************************/
#include "iic.h"
#include "common_api.h"

/**********function list******************************************************/
/*void IIC_Init(void);
void AUTH_RESET_PIN_Init(void);
void AUTH_CHIP_Rst(void);
uint32_t mop_Api_iic_write_data(uint8_t reg,uint8_t *orig,uint8_t len);
uint32_t mop_Api_iic_read_data(uint8_t reg,uint8_t *buf,uint8_t len);*/

/**********function list******************************************************/
void IIC_SCL_Init(void);
void IIC_SDA_Set(uint8_t mode);
void IIC_IO_Set(uint8_t index,uint8_t pinmode);
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(uint8_t ack_mode);
uint8_t IIC_Wait_Ack(void);
uint8_t IIC_Write_Byte(uint8_t value);
uint8_t IIC_Read_Byte(void);
void IIC_Delay(uint32_t dly_time );
void IIC_Stable(uint32_t dly_time);
void AUTH_RESET_PIN_Init(void);
uint8_t mop_Api_iic_dev_status(uint8_t opmode);
uint8_t mop_Api_iic_write_data(uint8_t reg,uint8_t *orig,uint8_t len);
uint8_t mop_Api_iic_read_data(uint8_t reg,uint8_t *buf,uint8_t len);
void AUTH_CHIP_Rst(void);

/**********funciton***********************************************************/
/*****************************************************************************
** Function name:
**      IIC_SCL_Init
**
** Descriptions:
**      IIC SCL line config
**
** parameters:
**      none
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_SCL_Init(void)
{
    PIO_out_config_api(IIC_SCL_PORT,PULL_UP_DISABLE,MULTI_DRIVE_DISABLE,\
                           IIC_SCL_PIN_NUM);
}

/*****************************************************************************
** Function name:
**      AUTH_RESET_PIN_Init
**
** Descriptions:
**      authentication chip reset line config
**
** parameters:
**      none
** Returned value:
**      None
** 
*****************************************************************************/
void AUTH_RESET_PIN_Init(void)
{
    PIO_out_config_api(AUTH_RST_PORT,PULL_UP_DISABLE,MULTI_DRIVE_DISABLE,\
                           AUTH_RST_PIN_NUM);
}

/*****************************************************************************
** Function name:
**      AUTH_CHIP_Rst
**
** Descriptions:
**      reset authentication chip and setup the iic addr
**
** parameters:
**      none
** Returned value:
**      None
** 
*****************************************************************************/
void AUTH_CHIP_Rst(void)
{
	IIC_IO_Set(AUTH_CHIP_RESET,RST_LOW);
	sys_tick_delay_us(20); 
	IIC_IO_Set(AUTH_CHIP_RESET,RST_HIGH);
	sys_tick_delay_ms(20); 
}


/*****************************************************************************
** Function name:
**      IIC_SDA_Set
**
** Descriptions:
**      IIC SDA line mode setting
**
** parameters:
**      uint8_t mode: SDA input/output mode setting
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_SDA_Set(uint8_t mode)
{
	if(mode == SDA_INPUT_MODE)
	{
        PIO_input_config_api(IIC_SDA_PORT,PULL_UP_DISABLE,FILTER_DISABLE,\
                             IIC_SDA_PIN_NUM);
	}
	else       //SDA_OUPUT_MODE
	{
        PIO_out_config_api(IIC_SDA_PORT,PULL_UP_DISABLE,\
                           MULTI_DRIVE_DISABLE,IIC_SDA_PIN_NUM);
	}
}
/*****************************************************************************
** Function name:
**      IIC_IO_Set
**
** Descriptions:
**      set scl sda  pin state
**
** parameters:
**      index----pin index
**      pinmode----pin output state
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_IO_Set(uint8_t index,uint8_t pinmode)
{
	switch(index)
	{
			case IIC_INDEX_SCL:
				if(SCL_LOW == pinmode)
				{
                    PIO_reset_bit(IIC_SCL_PORT,IIC_SCL_PIN_NUM); 	//Scl output low
				}
				else          //SCL_HIGH
				{
            		PIO_set_bit(IIC_SCL_PORT,IIC_SCL_PIN_NUM); 	//Scl output high
				}
				break;
			case IIC_INDEX_SDA:
				if(SDA_LOW == pinmode)
				{
            		PIO_reset_bit(IIC_SDA_PORT,IIC_SDA_PIN_NUM); 	//SDA output low
				}
				else          //SDA_HIGH
				{
            		PIO_set_bit(IIC_SDA_PORT,IIC_SDA_PIN_NUM); 	//SDA output high
				}
				break;
			case AUTH_CHIP_RESET:
                if(RST_LOW == pinmode)
                {
                    PIO_reset_bit(AUTH_RST_PORT,AUTH_RST_PIN_NUM); 	//RST output low
                }
                else        //RST_HIGH
                {
                    PIO_set_bit(AUTH_RST_PORT,AUTH_RST_PIN_NUM); 	//RST output high
                }
			break;
		default:
			break;
	}
}

/*****************************************************************************
** Function name:
**      IIC_Init
**
** Descriptions:
**      initation iic bus
**
** parameters:
**      none
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Init(void)
{
    IIC_SCL_Init();    
    IIC_SDA_Set(SDA_OUTPUT_MODE);
    AUTH_RESET_PIN_Init();
    IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
    IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);
}
/*****************************************************************************
** Function name:
**      IIC_Start
**
** Descriptions:
**      IIC start operata  START:when CLK is high,DATA change form high to low 
**
** parameters:
**      none
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Start(void)
{
	IIC_SDA_Set(SDA_OUTPUT_MODE);
	IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);
	IIC_Stable(IIC_STABLE_TIME);
	
	IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
    IIC_Delay(IIC_DATA_INTREVAL);
	IIC_IO_Set(IIC_INDEX_SDA,SDA_LOW);
    IIC_Delay(IIC_DATA_INTREVAL);
	IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW);	   //After send start,the clk must be pull low 
	IIC_Stable(IIC_STABLE_TIME);
}
/*****************************************************************************
** Function name:
**      IIC_Stop
**
** Descriptions:
**      IIC stop operata  STOP:when CLK is high DATA change form low to high 
**
** parameters:
**      None
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Stop(void)
{
	IIC_SDA_Set(SDA_OUTPUT_MODE);
	IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH); 
	IIC_IO_Set(IIC_INDEX_SDA,SDA_LOW);
    IIC_Delay(IIC_DATA_INTREVAL);
    IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);
    IIC_Delay(IIC_DATA_INTREVAL);
}
/*****************************************************************************
** Function name:
**      IIC_ACK
**
** Descriptions:
**      IIC Ack operata  ACK:SDA is low, and one clock, NACK:SDA is high ,and one clock 
**
** parameters:
**      mode: IIC_ACK or IIC_NACK
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Ack(uint8_t ack_mode)
{
	IIC_SDA_Set(SDA_OUTPUT_MODE);
	if(IIC_ACK == ack_mode)
    {
		IIC_IO_Set(IIC_INDEX_SDA,SDA_LOW);
	}
	else
	{
		IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);
	}
	IIC_Delay(IIC_DATA_INTREVAL);
    IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
	IIC_Delay(IIC_DATA_INTREVAL);
	IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW);
	IIC_Delay(IIC_DATA_INTREVAL);
}
/*****************************************************************************
** Function name:
**      IIC_Wait_Ack
**
** Descriptions:
**      waiting ack signer 
**
** parameters:
**      NONE
** Returned value:
**      IIC_ACK_RIGHT OR IIC_ACK_WRONG
** 
*****************************************************************************/
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	IIC_SDA_Set(SDA_INPUT_MODE);
	IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);
	IIC_Stable(IIC_STABLE_TIME);
	IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
	IIC_Stable(IIC_STABLE_TIME);	 
	while(PIO_read_bit(IIC_SDA_PORT,IIC_SDA_PIN_NUM))   //check sda pin
	{
		ucErrTime++;
		if(ucErrTime > IIC_WATI_ACK_TIME)
		{
			IIC_Stop();
			return IIC_ACK_WRONG;
		}
	}
	IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW);	   
	return IIC_ACK_RIGHT;  
}
/*****************************************************************************
** Function name:
**      IIC_Write_One_Byte
**
** Descriptions:
**      write one byte through IIC 
**
** parameters:
**      value: the value been written
** Returned value:
**      IIC_ACK_RIGHT OR IIC_ACK_WRONG
** 
*****************************************************************************/
uint8_t IIC_Write_Byte(uint8_t value)
{
    uint8_t bitcnt = 0,state;
	IIC_SDA_Set(SDA_OUTPUT_MODE);
	for(bitcnt = 0; bitcnt < 8; bitcnt++)
	{
        if((value << bitcnt) &(0x80))
		{
		    IIC_IO_Set(IIC_INDEX_SDA,SDA_HIGH);    
        }
		else
		{
            IIC_IO_Set(IIC_INDEX_SDA,SDA_LOW);
        }
		IIC_Delay(IIC_DATA_INTREVAL);
        IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
		IIC_Delay(IIC_DATA_INTREVAL);
		IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW);
	}
	state = IIC_Wait_Ack();
	IIC_Delay(IIC_DATA_INTREVAL);
	return state;
}
/*****************************************************************************
** Function name:
**      IIC_Read_One_Byte
**
** Descriptions:
**      read one byte through IIC 
**
** parameters:
**      None
** Returned value:
**      the value read form iic
** 
*****************************************************************************/
uint8_t IIC_Read_Byte(void)
{
	uint8_t bitcnt = 0,receive = 0;
	IIC_SDA_Set(SDA_INPUT_MODE);
    for(bitcnt = 0;bitcnt < 8;bitcnt++ )
	{
        IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW); 
        IIC_Delay(IIC_DATA_INTREVAL);
	    IIC_IO_Set(IIC_INDEX_SCL,SCL_HIGH);
        IIC_Delay(IIC_DATA_INTREVAL);
        receive=receive<<1;
        if(PIO_read_bit(IIC_SDA_PORT,IIC_SDA_PIN_NUM))
		{
			receive++;
        }
		IIC_Delay(IIC_DATA_INTREVAL); 
    }	
    IIC_IO_Set(IIC_INDEX_SCL,SCL_LOW); 
    IIC_Delay(IIC_DATA_INTREVAL);
    return receive;
}
/*****************************************************************************
** Function name:
**      IIC_Delay
**
** Descriptions:
**      IIC delay interval 
**
** parameters:
**      dly_time----delay time
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Delay(uint32_t dly_time )
{
    sys_tick_delay_us(dly_time);
}
/*****************************************************************************
** Function name:
**      IIC_Stable
**
** Descriptions:
**      IIC status stable time 
**
** parameters:
**      dly_time----stalbe delay time
** Returned value:
**      None
** 
*****************************************************************************/
void IIC_Stable(uint32_t dly_time)
{
	 sys_tick_delay_us(dly_time);
}

/*****************************************************************************
** Function name:
**      mop_Api_iic_dev_status
**
** Descriptions:
**      get the status of the device 
**
** parameters:
**      opmode----operate mode IIC_READ OR IIC_WRITE
** Returned value:
**      IIC_ACK_WRONG OR IIC_ACK_RIGHT
** 
*****************************************************************************/
uint8_t mop_Api_iic_dev_status(uint8_t opmode)
{
	uint8_t iic_ack,oprate_count = 0;

	for(oprate_count = 0;oprate_count< IIC_FAILE_TIME;oprate_count++)
	{
	    IIC_Start();
		iic_ack = IIC_Write_Byte(IIC_AUTH_ADDR|opmode);
		if(iic_ack == IIC_ACK_RIGHT)
		{
			return IIC_ACK_RIGHT;
		}
	}
	return IIC_ACK_WRONG;
}

/*****************************************************************************
** Function name:
**      mop_Api_iic_write_data
**
** Descriptions:
**            send datas to slave chip
**            return 0  mean send data failed.
**
** parameters:
**           reg----start register addr
**           orig---source data addr
**           len----data length to be writen
** Returned value:
**          IIC_ACK_RIGHT----read successfuly
**          IIC_ACK_WRONG----read failed
*****************************************************************************/
uint8_t mop_Api_iic_write_data(uint8_t reg,uint8_t *orig,uint8_t len)
{
    uint8_t bytecnt = 0,result,iic_ack;

    result = mop_Api_iic_dev_status(IIC_WRITE);
	if(IIC_ACK_WRONG == result)
		return IIC_ACK_WRONG;
	
	iic_ack = IIC_Write_Byte(reg);
	if(IIC_ACK_WRONG == iic_ack)
		return IIC_ACK_WRONG;
	
	for(bytecnt = 0; bytecnt < len; bytecnt++)
	{
        iic_ack = IIC_Write_Byte(*orig);
        if(IIC_ACK_WRONG == iic_ack)
			return IIC_ACK_WRONG;    
        orig++;
	}
	IIC_Stop();
	
	return IIC_ACK_RIGHT;
}

/*****************************************************************************
** Function name:
**      mop_Api_iic_read_data
**
** Descriptions:
**      read datas from slave chip 
**
** parameters:
**       reg----register start addr
**       buf----destination addr
**       len----data length to be read
** Returned value:
**      IIC_ACK_RIGHT----success
**      IIC_ACK_WRONG----failed
*****************************************************************************/
uint8_t mop_Api_iic_read_data(uint8_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t bytecnt = 0,result,iic_ack;

	result = mop_Api_iic_dev_status(IIC_WRITE);
	if(IIC_ACK_WRONG == result)
		return IIC_ACK_WRONG;

	iic_ack = IIC_Write_Byte(reg);
	if(IIC_ACK_WRONG == iic_ack)
		return IIC_ACK_WRONG;

	result = mop_Api_iic_dev_status(IIC_READ);
	if(IIC_ACK_WRONG == result)
		return IIC_ACK_WRONG;

	for(bytecnt = 0; bytecnt < len; bytecnt++)
	{
	    *buf = IIC_Read_Byte();
		IIC_Ack(IIC_ACK);	 
	    buf++;
	}
	*buf = IIC_Read_Byte();
	IIC_Ack(IIC_NACK);
	IIC_Stop();

	return IIC_ACK_RIGHT;
}

/*****************************************************************************
** Function name:
**      IIC_Init

** Descriptions:
**      initiate the iic bus for authentication coprocessor
**
** parameters:
**      none
** Returned value:
**      none
** 
*****************************************************************************/
/*void IIC_Init(void)
{
	AUTH_RESET_PIN_Init();
        AUTH_CHIP_Rst();
        TWI_init(TWI0);
}*/

/*****************************************************************************
** Function name:
**      mop_Api_iic_write_data

** Descriptions:
**      write data to authentication coprocessor
**
** parameters:
**      reg------start register addr
**      orig-----sorce data buffer
**      len------write data length
** Returned value:
**      return TWI_SUCCESS if write successfully
**      return TWI_INVALID_ARGUMENT if the arg is invalid
**      return TWI_RECEIVE_NACK if ACK did't received
*****************************************************************************/
/*uint32_t mop_Api_iic_write_data(uint8_t reg,uint8_t *orig,uint8_t len)
{
        twi_transfer_arg twi_read_arg;
        
        twi_read_arg.buffer = orig;
        twi_read_arg.deveic_addr = IIC_AUTH_ADDR>>1;
        twi_read_arg.inter_addr[0] = reg;
        twi_read_arg.inter_addr_length = 1;
        twi_read_arg.transfer_length = len;
        
        return(TWI_master_write(TWI0, &twi_read_arg));
}*/

/*****************************************************************************
** Function name:
**      mop_Api_iic_read_data

** Descriptions:
**      read data from authentication coprocessor
**
** parameters:
**      reg------start register addr
**      orig-----data buffer for saving data 
**      len------read data length
** Returned value:
**      return TWI_SUCCESS if write successfully
**      return TWI_INVALID_ARGUMENT if the arg is invalid
**      return TWI_RECEIVE_NACK if ACK did't received
*****************************************************************************/
/*uint32_t mop_Api_iic_read_data(uint8_t reg,uint8_t *buf,uint8_t len)
{
        twi_transfer_arg twi_read_arg;
        
        twi_read_arg.buffer = buf;
        twi_read_arg.deveic_addr = IIC_AUTH_ADDR>>1;
        twi_read_arg.inter_addr[0] = reg;
        twi_read_arg.inter_addr_length = 1;
        twi_read_arg.transfer_length = len;
        
        return(TWI_master_read(TWI0, &twi_read_arg));
}*/

/*****************************************************************************
** Function name:
**      AUTH_CHIP_Rst
**
** Descriptions:
**      reset the authentication coprocessor
**
** parameters:
**      none
** Returned value:
**      none
** 
*****************************************************************************/
/*void AUTH_CHIP_Rst(void)
{
	PIO_reset_bit(PIOA,4);
	sys_tick_delay_us(100); 
	PIO_set_bit(PIOA,4);
	sys_tick_delay_ms(20); 
}*/
/****************************************************************************/
